<script
	lang="ts"
	setup
>
import { clearNullData } from '@/utils'
import type { DataTableProps } from 'naive-ui'
import type { UnwrapRef } from 'vue'
import { onMounted, onUnmounted, ref, watch } from 'vue'

interface PageProps {
	pageSize: number;
	page: number;
	itemCount: number
}

const elRef = ref()
const height = ref(0)
const tableData = ref<any[]>([])
const _tableProps = ref<DataTableProps>({
	maxHeight: 300
})
const pagination = ref<PageProps>({
	pageSize: 20,
	page: 1,
	itemCount: 0
})
const emit = defineEmits(['search', 'reset', 'load'])
const props = withDefaults(
	defineProps<{
		tableProps?: UnwrapRef<DataTableProps> // 表格配置项
		params?: { [key: string]: any }
		tableRequest?: Function | null // 请求接口函数
		requestHook?: Function | null // 请求接口函数
	}>(),
	{}
)
onMounted(async () => {
	if (props.tableProps) {
		const { pagination: pg, data, ...other } = props.tableProps
		tableData.value = data || []
		_tableProps.value = {
			..._tableProps.value,
			...other
		}
		if (pg && typeof pg === 'object' && typeof pagination.value === 'object') {
			pagination.value = {
				pageSize: pg.pageSize || pagination.value.pageSize || 20,
				page: pg.page || pagination.value.page || 1,
				itemCount: pg.itemCount || pagination.value.itemCount || 0
			}
		}
	}

	resize()
	window.addEventListener('resize', resize, false)
	await getList()
})

onUnmounted(() => {
	window.removeEventListener('resize', resize, false)
})

watch(
	() => elRef.value,
	() => {
		if (elRef.value) {
			resize()
		}
	}
)
watch(
	() => props.tableProps?.loading,
	() => {
		_tableProps.value.loading = props.tableProps?.loading
	}
)
watch(
	() => pagination.value.itemCount,
	() => {
		resize()
	}
)
watch(
	() => props.tableProps?.data,
	() => {
		tableData.value = props.tableProps?.data || []
	}
)
watch(
	() => props.params,
	() => {
		reset()
	},
	{ deep: true }
)

async function reset() {
	clearFilter()
	await getList()
}

function clearFilter() {
	resetPage()
	tableData.value = []
	emit('reset')
}

function resetPage() {
	if (typeof pagination.value === 'object') {
		pagination.value.page = 1
		pagination.value.itemCount = 0
	}
}

function updateData(index: number, valueObj: any) {
	const item = tableData.value[index];
	if (item) {
		for (let key in valueObj) {
			item[key] = valueObj[key]
		}
		tableData.value[index] = {
			...item,
		}
	}
}

async function handlePageChange(currentPage: number) {
	if (typeof pagination.value === 'object') {
		pagination.value.page = currentPage
	}
	await getList()
}

function resize() {
	if (elRef.value && elRef.value.parentElement) {
		// 表格高度=页面高度 - 顶部距离 - 底部外边距
		height.value = innerHeight - elRef.value.getBoundingClientRect().top - 20

		_tableProps.value.maxHeight =
			height.value
			- 15 // 滚动条占比，防止出现上滚动条
			- 48  // 表头高度
			- 28 // 分页器高度
	}
}

function deleteItem(key: string, value: string | number) {
	if (pagination.value.itemCount <= pagination.value.pageSize) {
		tableData.value = deepFilter(tableData.value, (item) => {
			return item[key] !== value
		})
	} else {
		getList()
	}
}

function deepFilter(children: any[], filter: (item: any) => boolean) {
	return children.filter(filter).map(i => {
		if (i.children?.length) {
			i.children = deepFilter(children, filter)
		}
		return i;
	})
}

async function getList(params = {}) {
	if (props.tableRequest && typeof props.tableRequest === 'function' && !_tableProps.value.loading) {
		_tableProps.value.loading = true
		tableData.value = []
		let p: any = {}
		if (props.params?.path && typeof props.params.path === 'object') {
			if (typeof pagination.value === 'object') {
				p = {
					path: props.params.path,
					params: {
						pageSize: pagination.value.pageSize,
						pageNum: pagination.value.page
					}
				}
			}
			p = {
				...p,
				params: {
					...p.params,
					...(props.params.params || {}),
					...params
				}
			}
		} else {
			if (typeof pagination.value === 'object') {
				p = {
					pageSize: pagination.value.pageSize,
					pageNum: pagination.value.page
				}
			}
			p = {
				...p,
				...props.params,
				...params
			}
		}

		let { data, total } = await props.tableRequest(clearNullData(p))
		_tableProps.value.loading = false
		if (data) {
			if (props.requestHook) {
				tableData.value = props.requestHook(data)
			} else {
				tableData.value = data
			}
			if (typeof pagination.value === 'object') {
				pagination.value.itemCount = total || data.length
			}

			if (total === undefined) {
				pagination.value.pageSize = data.length || 20
			}
		}
		emit('load', data || [])
		return data || []
	}
}

defineExpose({
	reload: getList,
	deleteItem: deleteItem,
	clear: clearFilter,
	reset: reset,
	updateData: updateData,
	el: elRef.value
})
</script>

<template>
	<div
		ref="elRef"
		:style="{ maxHeight: height + 'px' }"
	>
		<n-data-table
			:data="tableData"
			:pagination="pagination"
			:remote="true"
			v-bind="_tableProps"
			@update:page="handlePageChange"
		/>
	</div>
</template>

<style
	lang="less"
	scoped
>
:deep([data-col-key='actions']) {
	> * {
		&:not(:last-child) {
			margin-right: 15px;
		}
	}
}
</style>
